package com.verify;

import com.aliyuncs.exceptions.ClientException;
import com.domain.*;
import com.domainVO.IssueLabelIdsVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mapper.helping.*;
import com.mapper.living.UserDao;
import com.util.AliYunUtil;
import com.util.QiNiuYunUtils;
import com.util.UserUtil;
import com.util.WeiXinUtil;
import living.com.result.ApiResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *     用户认证逻辑判断统一处理类
 * </p>
 * @author 大忽悠
 * @create 2022/2/10 11:01
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class VerifyAspect {
    private final UserDao userDao;
     private final WeiXinUtil weiXinUtil;
     private final AliYunUtil aliYunUtil;
    private final IssueCommentMapper issueCommentMapper;
    private final IssueCommentResponseMapper issueCommentResponseMapper;
    private final IssueMapper issueMapper;
    private final IssueCommentResponseGrandsonMapper issueCommentResponseGrandsonMapper;
    private static final ObjectMapper objectMapper=new ObjectMapper();
    private final QiNiuYunUtils qiNiuYunUtils;
    /**
     * 只对controller包下的方法进行处理
     */
    @Pointcut("execution(public * com.controller.*.*(..))")
    public void point(){};

    /**
     * 判断当前用户是否认证,没有认证执行方法的,抛出异常
     */
    @Around("point()")
    public Object userVerify(ProceedingJoinPoint joinPoint) throws Throwable {
        Method targetMethod = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //判断方法上是否存在@Verify注解
        if(!targetMethod.isAnnotationPresent(UserVerify.class))
        {
            //异常要向上抛出
            return joinPoint.proceed();
        }
        log.info("当前需要用户认证的方法为: {}",targetMethod.getName());
        //用户是否认证
        if(UserUtil.getUser().getIsVerify()==1)
        {
            log.info("需要用户认证的方法 {},认证成功!",targetMethod.getName());
            return joinPoint.proceed();
        }
        log.info("需要用户认证的方法 {},认证失败!",targetMethod.getName());
        throw  new IllegalArgumentException("用户未认证,请先认证");
    }


    /**
     * 需要微信认证的方法，返回值必须是ApiResult<Integer>,对应文本的id
     * 进行问题和标签提交时微信认证相关处理
     */
    @Around("point()")
    @Transactional(value = "primaryTransactionManager")
    public Object weiXinVerify(ProceedingJoinPoint joinPoint) throws Throwable {
        Method targetMethod = ((MethodSignature) joinPoint.getSignature()).getMethod();
        if(!targetMethod.isAnnotationPresent(WeiXinVerify.class))
        {
             return joinPoint.proceed();
        }
         log.info("当前需要微信认证的方法为: {}",targetMethod.getName());
        ApiResult<Integer> result = (ApiResult<Integer>) joinPoint.proceed();
        isWeiXinVerify(targetMethod,joinPoint.getArgs(),targetMethod.getAnnotation(WeiXinVerify.class),result.getData());
        return result;
    }


    /**
     * 微信对内容进行审核
     */
    private boolean isWeiXinVerify(Method method,Object[] args,WeiXinVerify weiXinVerify,Integer text_id) throws IOException, ClassNotFoundException, ClientException {
        Assert.isTrue(args.length>=weiXinVerify.paramIndex(),"微信验证注解,参数索引越界");
        //获取传入的参数值
        Object parameValue = args[weiXinVerify.paramIndex()];
        //获取参数名
        String paramName = weiXinVerify.paramName();
        //获取文本类型
        WeiXinUtil.WeiXinCheckTextType weiXinCheckTextType = WeiXinUtil.WeiXinCheckTextType.getTargetType(weiXinVerify.weiXinVerifyType());
        //解析出需要审核的文本内容
        String checkText = getCheckText(paramName, parameValue);
        //发布者id
        Integer publisherId = getPublisherId(text_id, weiXinCheckTextType);
        String openid=null;
        //为null说明为标签
        if(publisherId!=null)
        {
            //获取发布者的openId
            openid = userDao.getUserById(publisherId).getOpenid();
        }
        //先判断是否需要审核图片和视频
        boolean needImgCheck = weiXinVerify.needImgCheck();
        boolean needVideoCheck = weiXinVerify.needVideoCheck();
        if(needImgCheck)
        {
            aliYunUtil.checkImg(getPicUrls(weiXinCheckTextType,text_id),weiXinCheckTextType,text_id,publisherId,openid);
        }
        if(needVideoCheck)
        {
            aliYunUtil.videoCheck(getVideoUrls(weiXinCheckTextType,text_id),weiXinCheckTextType,text_id,publisherId,openid);
        }
        //文本内容,文本类型,文本id,发布者id,发布者openId
        weiXinUtil.checkText(checkText,weiXinCheckTextType,text_id,publisherId,openid);
        return true;
    }

    private List<String> getVideoUrls(WeiXinUtil.WeiXinCheckTextType weiXinCheckTextType, Integer text_id) throws JsonProcessingException {
        //解析问题
        if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_TITLE)||weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_DETAILS))
        {
            Issue issue = issueMapper.selectById(text_id);
            return commonFilePathOperations(issue.getVideos());
        }
        else if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.FATHER_COMMENT))
        {
            IssueComment issueComment = issueCommentMapper.selectById(text_id);
            return commonFilePathOperations(issueComment.getVideos());
        }
        throw new IllegalArgumentException("此类型暂不支持视频审核");
    }

    private List<String> getPicUrls(WeiXinUtil.WeiXinCheckTextType weiXinCheckTextType, Integer text_id) throws JsonProcessingException {
        //解析问题
        if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_TITLE)||weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_DETAILS))
        {
            Issue issue = issueMapper.selectById(text_id);
            return commonFilePathOperations(issue.getImgs());
        }
        else if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.FATHER_COMMENT))
        {
            IssueComment issueComment = issueCommentMapper.selectById(text_id);
            return commonFilePathOperations(issueComment.getImgs());
        }
        throw new IllegalArgumentException("此类型暂不支持图片审核");
    }

    private List<String> commonFilePathOperations(String paths) throws JsonProcessingException {
        if(paths!=null&&paths!=""&&paths!="[]")
        {
            List<String> list = objectMapper.readValue(paths, List.class);
            return list.stream().map(path->{
                return qiNiuYunUtils.getFilePrefix()+path;
            }).collect(Collectors.toList());
        }
        return null;
    }



    /**
     * @return 返回需要进行审核的文本内容
     */
    private String getCheckText(String pojoName,Object value)
    {
        if(pojoName.equals("String"))
        {
            return pojoName;
        }
        else if(pojoName.equals("IssueLabelIdsVO")) {
            IssueLabelIdsVO issueLabelIdsVO = (IssueLabelIdsVO) value;
            Issue issue = issueLabelIdsVO.getIssue();
            return issue.getQuestionTitle()+" "+issue.getQuestionDetails();
        }
        else if(pojoName.equals("Label"))
        {
            Label label = (Label) value;
            return label.getContent();
        }
        throw new IllegalArgumentException("审核文本传入的paramName参数名有误");
    }

    /**
     * 查询当前文本对应的用户id
     */
    private Integer getPublisherId(Integer text_id, WeiXinUtil.WeiXinCheckTextType weiXinCheckTextType) {
        if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.FATHER_COMMENT))
      {
        //父评论
          IssueComment issueComment = issueCommentMapper.selectById(text_id);
          log.info("当前需要审核的文本为父评论,对应父评论为: {}",issueComment);
          return issueComment.getUserId();
      }else  if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.SON_COMMENT))
        {
            Integer u_id=-1;
            //子评论
            IssueCommentResponse issueCommentResponse = issueCommentResponseMapper.selectById(text_id);
            if((u_id=issueCommentResponse.getFromUserId())==0)
            {
                //如果是匿名版主发布的评论,对应的fromUserId为0--去找回答要版主的id
                IssueComment issueComment = issueCommentMapper.selectById(issueCommentResponse.getFatherCommentId());
                u_id=issueComment.getUserId();
            }
            log.info("当前需要审核的文本为子评论,对应子评论为: {}",issueCommentResponse);
            return u_id;
        }
        else if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_DETAILS)||weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.ISSUE_TITLE))
        {
            log.info("当前需要审核的文本为问题,对应问题id为: {}",text_id);
            return issueMapper.selectById(text_id).getUserId();
        }
        else if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.LABEL_CONTENT))
        {
            //标签不需要关联用户
            log.info("当前需要审核的文本为标签,对应标签id为: {}",text_id);
            return null;
        }else if(weiXinCheckTextType.equals(WeiXinUtil.WeiXinCheckTextType.GRANT_SON_COMMENT))
        {
            IssueCommentResponseGrandson issueCommentResponseGrandson = issueCommentResponseGrandsonMapper.selectById(text_id);
            Integer u_id=issueCommentResponseGrandson.getFromUserId();
            if(u_id==0)
            {
                IssueCommentResponse issueCommentResponse = issueCommentResponseMapper.selectById(issueCommentResponseGrandson.getFatherCommentId());
                //如果是匿名版主发布的评论,对应的fromUserId为0---找到回答的版主要用户id
                u_id=issueCommentMapper.selectById
                        (issueCommentResponse.getFatherCommentId()).getUserId();
            }
            log.info("当前需要审核的文本为孙子评论,对应孙子评论id为: {}",text_id);
            return u_id;
        }
        throw new IllegalArgumentException("getPublisherId方法中传入的WeiXinCheckTextType有误");
    }


}
